from constants import GAN,ZHI
"""提取干支时间"""


def findZodiacWord(search_string, kw, as_text=True, strict_mode=False):
    import re
    if strict_mode:
        pattern = f'(?P<year>(?P<gan>[甲乙丙丁戊己庚辛壬癸])(?P<zhi>[子丑寅卯辰巳午未申酉戌亥]){kw})'
    else:
        pattern = f'(?P<year>(?P<gan>[甲乙丙丁戊己庚辛壬癸])?(?P<zhi>[子丑寅卯辰巳午未申酉戌亥]){kw})'
    match = re.search(pattern, search_string)

    if match:
        gan = match.group('gan') if match.group('gan') else ''
        zhi = match.group('zhi')
        if as_text:
            return gan + zhi + kw
        else:
            return [GAN.index(gan) if gan else gan, ZHI.index(zhi) if zhi else zhi]
    else:
        return '' if as_text else [None, None]


def extract_time_from_text(text, args):
    # time_line = text.split('\n')[1] if '\n' in text else text
    time_line = text
    return [findZodiacWord(time_line, tag) for tag in args]


def extract_int_from_text(text):
    # time_line = text.split('\n')[1] if '\n' in text else text
    time_line = text
    _1, _2 = findZodiacWord(time_line, '年', False)
    _, _3 = findZodiacWord(time_line, '月', False)
    _4, _5 = findZodiacWord(time_line, '日', False, strict_mode=True)
    _, _6 = findZodiacWord(time_line, '时', False)
    return [_1, _2, _3, _4, _5, _6]


'''提取卦名'''


def filter_indices(li, start_idx):
    # 筛选出满足条件的元素
    temp_list = [(idx, gua_name) for idx, gua_name in li if 0 < idx - start_idx < 20]
    return temp_list if temp_list else li


def find_2char_index(text, search_dic=None):
    # 检查是否有卦象的繁体字/模糊字。遍历字典，繁体替换为简体
    if search_dic is None:
        search_dic = GUA_NAME

    replace_map = {
        "離": "离", "濟": "济", "訟": "讼", "損": "损", "師": "师", "豐": "丰", "節": "节", "晉": "晋", "剝": "剥",
        "恆": "恒", "觀": "观", "過": "过", "隨": "随", "蟲": "蛊", "蠱": "蛊", "頤": "颐", "復": "复", "臨": "临",
        "賁": "贲", "無妄": "无妄", "謙": "谦", "渙": "涣", "漸": "渐", "歸": "归", "蓄": "畜", "遯": "遁",
        "為火": "为火", "大壯": "大壮", "為水": "为水", "為雷": "为雷", "兌為": "兑为", "為天": "为天", "為地": "为地",
        "為風": "为风", "為山": "为山", "風": "风", "澤": "泽", '曰': "日", "天风□": "天风姤", "天山□": "天山遁",
        "泽天□": "泽天夬", "水山赛": "水山蹇", "暌": "睽",
    }
    for old_word, new_word in replace_map.items():
        text = text.replace(old_word, new_word)

    # 遍历卦名g，在字符串s找到查找【卦名g】的【索引位置i】。(i,g)保存在列表s_idxes中。按照i排序，key=ele[0]

    # 只能找到出现一次的，出现两次以上的被忽略了。
    # s_idxes = [(s.find(g), g) for g in search_dic if s.find(g) != -1]

    # 能找到出现两次以上的：
    def find_all_occurrences(search_string, matching_name):
        s_idxes = []
        start_idx = 0

        # 死循环search字符串search_string所有的matching_name
        while True:

            # 指定了字符串s找字符g的起始索引：start_idx；找不到就退出循环
            idx = search_string.find(matching_name, start_idx)
            if idx == -1:
                break

            # 准备查找string的下一个matching_name，update起始索引start_idx
            start_idx = idx + len(matching_name)

            # 八卦名+宫的string不算进去；防止出现：乾宫/坎宫被算进去
            try:
                if search_string[start_idx] != "宫":
                    s_idxes.append((idx, matching_name))
            except IndexError:
                pass

        return s_idxes

    s_idxes = []
    for g in search_dic:
        s_idxes.extend(find_all_occurrences(text, g))

    s_idxes.sort(key=lambda x: x[0])

    start_idx = text.find('得')
    if start_idx != -1 and len(s_idxes) >= 2:
        s_idxes = filter_indices(s_idxes, start_idx)

    return s_idxes


def identify_GuaName(s, Exact_match=False, as_text=True, full_match=False):
    from constants import GUA_NAME, GUA_NAMES
    # GuaName_li[idx]为元组(s_idx,GuaName)

    # 能否的bug，识别出否卦来了
    s = s.replace("能否", "").replace("是否", "").replace("成否", "")
    s = s + '助'

    refer_lst = GUA_NAME
    if Exact_match:
        refer_lst = GUA_NAMES

    GuaName_li = find_2char_index(s, search_dic=refer_lst)

    find_out = []
    if (length := len(GuaName_li)) == 1:
        # 卦名GuaName_li[0][1]在 卦名列表guaname 中的序号
        find_out = [refer_lst.index(GuaName_li[0][1])]
    elif length == 2:
        find_out = list(map(lambda x: refer_lst.index(x), (GuaName_li[0][1], GuaName_li[1][
            1])))  # find_out = [refer_lst.index(GuaName_li[0][1]),refer_lst.index(GuaName_li[1][1])]

    elif length >= 3 and not full_match:
        # 找到相邻差距最小的两个数
        neibor_least_num = []
        mindiff = 100
        for i in range(len(GuaName_li) - 1):
            diff = GuaName_li[i + 1][0] - GuaName_li[i][0]
            if diff < mindiff:
                mindiff = diff
                neibor_least_num = [GuaName_li[i], GuaName_li[i + 1]]  # 此为元组
        find_out = list(map(lambda x: refer_lst.index(x), (neibor_least_num[0][1], neibor_least_num[1][1])))
    elif full_match:
        find_out = list(map(lambda x: refer_lst.index(x), [li[1] for li in GuaName_li]))
    if as_text:
        return ' '.join([str(n) for n in find_out])
    else:
        return find_out
